import json
import os
import re
from typing import Dict, List, Union, Set, Tuple, Optional
from urllib.parse import urlparse

class AnchorManager:
    """管理文档中的锚点，确保唯一性并提供验证"""
    
    def __init__(self):
        self.used_anchors: Set[str] = set()
        self.title_to_anchor: Dict[str, str] = {}
    
    def generate_anchor(self, title: str) -> str:
        """
        为标题生成唯一的锚点
        
        Args:
            title: 需要生成锚点的标题文本
            
        Returns:
            生成的唯一锚点
        """
        if title in self.title_to_anchor:
            return self.title_to_anchor[title]
            
        base_anchor = format_anchor(title)
        if not base_anchor:  # 处理空锚点情况
            base_anchor = "section"
            
        anchor = base_anchor
        counter = 1
        while anchor in self.used_anchors:
            anchor = f"{base_anchor}-{counter}"
            counter += 1
            
        self.used_anchors.add(anchor)
        self.title_to_anchor[title] = anchor
        return anchor
    
    def get_anchor(self, title: str) -> Optional[str]:
        """获取已存在的锚点，如果不存在返回None"""
        return self.title_to_anchor.get(title)

class LinkManager:
    """管理文档中的链接处理"""
    
    def __init__(self, formats: Dict[str, Dict]):
        self.formats = formats
        self.link_mappings = formats.get("links", {}) if formats else {}
    
    def validate_url(self, url: str) -> bool:
        """验证URL格式是否有效"""
        try:
            result = urlparse(url)
            return all([result.scheme, result.netloc]) or url.startswith("#")
        except:
            return False
    
    def resolve_link(self, link_id: str) -> str:
        """解析链接ID到实际URL"""
        if link_id in self.link_mappings:
            url = self.link_mappings[link_id]
            return url if self.validate_url(url) else link_id
        return link_id
    
    def format_link(self, text: str, link: str, description: str = "") -> str:
        """格式化链接文本"""
        resolved_link = self.resolve_link(link)
        if description:
            return f"[{text}]({resolved_link}) - {description}"
        return f"[{text}]({resolved_link})"

def format_code_block(language: str, content: str) -> str:
    """
    Format a code block with proper syntax highlighting
    
    Args:
        language: Programming language for syntax highlighting
        content: Code content
        
    Returns:
        Formatted code block string
    """
    return f"```{language}\n{content}\n```"

def format_inline_code(language: str, content: str) -> str:
    """
    Format inline code with proper syntax highlighting
    
    Args:
        language: Programming language for syntax highlighting
        content: Code content
        
    Returns:
        Formatted inline code string
    """
    return f"`{content}`"

def format_image(image_data: Dict) -> str:
    """
    Format an image with alt text and optional title
    
    Args:
        image_data: Dictionary containing image information
        
    Returns:
        Formatted image string
    """
    alt_text = image_data.get("alt", "Image")
    url = image_data.get("url", "")
    title = image_data.get("title", "")
    
    if title:
        return f"![{alt_text}]({url} \"{title}\")"
    return f"![{alt_text}]({url})"

def format_link(link_data: Dict) -> str:
    """
    Format a link with optional description
    
    Args:
        link_data: Dictionary containing link information
        
    Returns:
        Formatted link string
    """
    text = link_data.get("text", "")
    link = link_data.get("link", "")
    description = link_data.get("description", "")
    
    if description:
        return f"[{text}]({link}) - {description}"
    return f"[{text}]({link})"

def format_anchor(title: str) -> str:
    """
    Format an anchor for a section using the heading text
    
    Args:
        title: The heading text
        
    Returns:
        Formatted anchor string
    """
    # 将标题转换为小写，替换空格为连字符
    anchor = title.lower().replace(' ', '-')
    # 移除任何非字母数字字符
    anchor = re.sub(r'[^a-z0-9-]', '', anchor)
    return anchor

def process_references(references: Dict, anchor_manager: AnchorManager) -> str:
    """处理参考部分，使用AnchorManager生成锚点"""
    if not isinstance(references, dict):
        return ""
        
    result = []
    if "title" in references:
        result.append(f"## {references['title']}\n")
        
    if "items" in references:
        for item in references["items"]:
            if isinstance(item, dict) and "text" in item and "link" in item:
                text = item["text"]
                anchor = anchor_manager.generate_anchor(text)
                result.append(f"- [{text}](#{anchor})")
                
    return "\n".join(result) + "\n\n"

def process_formats(formats: Dict) -> Dict[str, Dict]:
    """
    Process the formats section of the JSON source
    
    Args:
        formats: Formats dictionary containing links, code_blocks, code_examples, and images
        
    Returns:
        Dictionary containing processed format mappings
    """
    return {
        "links": formats.get("links", {}),
        "code_blocks": formats.get("code_blocks", {}),
        "code_examples": formats.get("code_examples", {}),
        "images": formats.get("images", {})
    }

def process_mixed_content(content: Union[str, Dict, List], 
                         formats: Dict[str, Dict] = None,
                         anchor_manager: Optional[AnchorManager] = None,
                         link_manager: Optional[LinkManager] = None) -> str:
    """
    处理混合内容，支持文本、代码块、链接等
    """
    if isinstance(content, str):
        if formats:
            # 使用LinkManager处理链接引用
            if link_manager:
                # 处理形如 [text](#anchor) 的链接
                def replace_anchor_link(match):
                    text = match.group(1)
                    anchor = match.group(2)
                    # 检查是否是formats.links中定义的链接
                    if anchor in link_manager.link_mappings:
                        return f"[{text}]({link_manager.resolve_link(anchor)})"
                    return match.group(0)
                
                # 使用正则表达式匹配 [text](#anchor) 格式的链接
                content = re.sub(r'\[([^\]]+)\]\(#([^\)]+)\)', replace_anchor_link, content)
                
                # 处理形如 (link_id) 的链接引用
                for link_id in link_manager.link_mappings:
                    if f"({link_id})" in content:
                        resolved_link = link_manager.resolve_link(link_id)
                        content = content.replace(f"({link_id})", f"({resolved_link})")
        return content
    
    elif isinstance(content, dict):
        if "type" in content and content["type"] == "code":
            # 处理代码块逻辑保持不变
            return format_code_block(content.get("language", ""), content.get("content", ""))
        elif "type" in content and content["type"] == "image":
            return format_image(content)
        elif "link" in content:
            # 使用LinkManager处理链接
            if link_manager:
                text = content.get("text", "")
                link = content["link"]
                description = content.get("description", "")
                
                # 处理内部锚点链接
                if link.startswith("#") and anchor_manager:
                    # 移除开头的#并查找对应的锚点
                    title = link[1:]
                    anchor = anchor_manager.get_anchor(title)
                    if anchor:
                        return f"[{text}](#{anchor})"
                
                return link_manager.format_link(text, link, description)
            
        return content.get("text", str(content))
    
    elif isinstance(content, list):
        result = []
        for item in content:
            processed = process_mixed_content(item, formats, anchor_manager, link_manager)
            if processed:
                result.append(processed)
        return "".join(result)
    
    return str(content)

def process_items(items: List[Union[str, Dict]], formats: Dict[str, Dict] = None) -> str:
    result = []
    for item in items:
        if isinstance(item, dict):
            if "type" in item:
                if item["type"] == "code":
                    language = item.get("language", "")
                    code_content = item.get("content", "")
                    if "\n" not in code_content:
                        result.append(f"- {format_inline_code(language, code_content)}")
                    else:
                        result.append(format_code_block(language, code_content))
                elif item["type"] == "image":
                    result.append(f"- {format_image(item)}")
            elif "name" in item or "text" in item:

                display_text = item.get("name", item.get("text", ""))
                link_url = item.get("link", "")
                description = item.get("description", "")

                print("formats 是否存在:", bool(formats))  # 检查 formats 是否非空

                # 检查是否是formats中定义的链接
                if formats and "links" in formats and link_url in formats["links"]:
                    link_url = formats["links"][link_url]

                if link_url:
                    if description:
                        result.append(f"- [{display_text}]({link_url}) - {description}")
                    else:
                        result.append(f"- [{display_text}]({link_url})")
                else:
                    result.append(f"- {display_text}")
            elif "link" in item:

                # 检查是否需要从formats.links中获取映射的URL
                if formats and "links" in formats and item["link"] in formats["links"]:

                    item = item.copy()  # 创建副本以避免修改原始数据
                    item["link"] = formats["links"][item["link"]]

                result.append(f"- {format_link(item)}")
            else:
                result.append(f"- {process_mixed_content(item, formats)}")
        else:
            result.append(f"- {process_mixed_content(item, formats)}")
    return "\n".join(result) + "\n"

def process_code_example(code_example: Dict) -> str:
    """
    Process a code example
    
    Args:
        code_example: Code example dictionary
        
    Returns:
        Formatted code example string
    """
    if not isinstance(code_example, dict):
        return str(code_example)
        
    if "code" in code_example:
        code_data = code_example["code"]
        language = code_data.get("language", "")
        code_content = code_data.get("content", "")
        return format_code_block(language, code_content)
    elif "type" in code_example and code_example["type"] == "code":
        language = code_example.get("language", "")
        code_content = code_example.get("content", "")
        return format_code_block(language, code_content)
    return str(code_example)

def json_to_markdown(data: Union[Dict, List], heading_level: int = 1) -> str:
    """
    转换JSON数据到Markdown格式
    
    Args:
        data: JSON数据
        heading_level: 当前标题级别
        
    Returns:
        转换后的Markdown字符串
    """
    markdown = ""
    anchor_manager = AnchorManager()
    
    if isinstance(data, dict):
        # 处理格式定义
        formats = process_formats(data.get("formats", {}))
        link_manager = LinkManager(formats)
        
        if "title" in data and "content" in data:
            # 添加主标题并生成锚点
            title = data['title']
            anchor = anchor_manager.generate_anchor(title)
            markdown += f"# {title} <a id=\"{anchor}\"></a>\n\n"
            
            content = data["content"]
            if isinstance(content, dict):
                # 处理介绍部分
                if "introduction" in content:
                    markdown += f"{process_mixed_content(content['introduction'], formats, anchor_manager, link_manager)}\n\n"
                
                # 处理引用部分
                if "references" in content:
                    markdown += process_references(content["references"], anchor_manager)
                
                # 处理章节
                if "sections" in content:
                    for section in content["sections"]:
                        if isinstance(section, dict):
                            # 处理章节标题和锚点
                            if "title" in section:
                                title = section["title"]
                                anchor = anchor_manager.generate_anchor(title)
                                markdown += f"## {title} <a id=\"{anchor}\"></a>\n\n"
                            
                            # 处理章节内容
                            if "content" in section:
                                markdown += f"{process_mixed_content(section['content'], formats, anchor_manager, link_manager)}\n\n"
                            
                            # 处理图片
                            if "image" in section:
                                image = section["image"]
                                if isinstance(image, str) and formats and image in formats.get("images", {}):
                                    markdown += f"{format_image(formats['images'][image])}\n\n"
                                elif isinstance(image, dict):
                                    markdown += f"{format_image(image)}\n\n"
                                else:
                                    print(f"Warning: Invalid image format in section: {image}")
                            
                            # 处理代码示例
                            if "code_example" in section:
                                if isinstance(section["code_example"], str) and section["code_example"] in formats.get("code_examples", {}):
                                    code_data = formats["code_examples"][section["code_example"]]
                                    markdown += f"{format_code_block(code_data.get('language', ''), code_data.get('content', ''))}\n\n"
                                else:
                                    print(section['code_example'])
                                    markdown += f"{process_code_example(section['code_example'])}\n\n"
                            
                            # 处理列表项
                            if "items" in section:
                                markdown += process_items(section["items"], formats) + "\n"
                            
                            # 处理子章节
                            if "subsections" in section:
                                for subsection in section["subsections"]:
                                    if isinstance(subsection, dict):
                                        if "title" in subsection:
                                            title = subsection["title"]
                                            anchor = anchor_manager.generate_anchor(title)
                                            markdown += f"### {title} <a id=\"{anchor}\"></a>\n\n"
                                        
                                        if "content" in subsection:
                                            markdown += f"{process_mixed_content(subsection['content'], formats, anchor_manager, link_manager)}\n\n"
                                        
                                        # 处理子章节图片
                                        if "image" in subsection:
                                            image = subsection["image"]
                                            if isinstance(image, str) and formats and image in formats.get("images", {}):
                                                markdown += f"{format_image(formats['images'][image])}\n\n"
                                            elif isinstance(image, dict):
                                                markdown += f"{format_image(image)}\n\n"
                                            else:
                                                print(f"Warning: Invalid image format in subsection: {image}")
                                        
                                        # 处理子章节的代码示例
                                        if "code_example" in subsection:
                                            code_example = subsection["code_example"]
                                            print(f"Debug - code_example: {code_example}")
                                            print(f"Debug - formats: {formats}")
                                            if isinstance(code_example, str):
                                                if formats and "code_examples" in formats:
                                                    print(f"Debug - code_examples keys: {formats['code_examples'].keys()}")
                                                    if code_example in formats["code_examples"]:
                                                        code_data = formats["code_examples"][code_example]
                                                        markdown += f"{format_code_block(code_data.get('language', ''), code_data.get('content', ''))}\n\n"
                                                    else:
                                                        print(f"Warning: Code example reference not found in formats: {code_example}")
                                                else:
                                                    print(f"Warning: formats or code_examples not found")
                                            elif isinstance(code_example, dict):
                                                markdown += f"{process_code_example(code_example)}\n\n"
                                            else:
                                                print(f"Warning: Invalid code example format: {code_example}")

                                        # 处理子章节的列表项
                                        if "items" in subsection:
                                            markdown += process_items(subsection["items"], formats) + "\n"
    
    return markdown

def save_json_to_markdown(json_data: Union[Dict, List], output_file: str) -> None:
    """
    Save JSON source to a Markdown file
    
    Args:
        json_data: JSON source to convert
        output_file: Path to the output Markdown file
    """
    markdown = json_to_markdown(json_data)
    
    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(markdown)

def load_json_from_file(file_path: str) -> Union[Dict, List]:
    """
    Load JSON source from a file
    
    Args:
        file_path: Path to the JSON file
        
    Returns:
        Union[Dict, List]: Loaded JSON source
    """
    with open(file_path, 'r', encoding='utf-8') as f:
        return json.load(f)

def main():
    # 从JSON文件加载数据
    json_data = load_json_from_file('../output/spring-ai/1.0/json/concepts.json')
    
    # 转换为Markdown并保存
    save_json_to_markdown(json_data, "../output/spring-ai/1.0/content/concepts.md")
    print("Markdown file has been created successfully!")

if __name__ == "__main__":
    main()